package en.edu.zxj.mq.mqserver.core;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description：表示一个要传递的消息
 * 此处的 Message 对象, 是需要能够在网络上传输, 并且也需要能写入到文件中.
 * 此时就需要针对 Message 进行序列化和反序列化.
 * 此处使用 标准库 自带的 序列化/反序列化 操作.
 *
 * @author: zxj
 * @date: 2024-02-25
 * @time: 20:55:17
 */
@Data
@Component
public class Message implements Serializable {
    // Message 核心属性
    private BasicProperties basicProperties = new BasicProperties();
    // 存储需要传输的消息, 使用字节的方式存储
    private byte[] body;

    // 辅助属性

    /**
     * 一个文件中会存储很多信息, 如何找到某个消息, 在文件中的具体位置呢?
     * 使用下列的两个偏移量进行表示, [offset, offsetEnd)
     * 这两个属性并不需要被反序列化保存到文件中, 此时信息一旦被写入文件之后, 所在的位置就固定了, 并不需要单独存储
     * 这两个属性存在的目的, 主要是为了让内存中的 Message 对象, 能够快速找到对应硬盘上的 Message 位置.
     **/
    private transient long offsetBeg = 0; // 消息数据开头距离文件开头的偏移位置 (单位是字节)
    private transient long offsetEnd = 0; // 消息数据结尾距离文件开头的偏移位置 (单位是字节)

    /**
     * 使用这个属性表示该消息在文件中是否是有效信息. (针对文件中的信息, 如果删除, 使用逻辑删除的方式)
     * 0x1 表示有效, 0x0 表示无效
     **/
    private byte isValid = 0x1;


    /**
     * @description: 工厂模式创建 Message 实例
     * 创建一个工厂方法, 让工厂方法帮我们封装一下创建 Message 对象的过程
     * 这个方法中创建的 Message 对象, 会自动生成唯一的 MessageId
     * 万一 routingKey 和 basicProperties 里的 routingKey 冲突, 以外面的为主
     **/
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties, byte[] body) {
        Message message = new Message();
        if (basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        // 此处生成的 MessageId 以 M- 作为前缀.
        message.setMessageId("M-" + UUID.randomUUID());
        message.setRoutingKey(routingKey);
        message.setBody(body);
        /* 此处是把 body 和 basicProperties 先设置出来. 他俩是 Message 的核心内容.
        而 offsetBeg, offsetEnd, isValid, 则是消息持久化的时候才会用到. 在把消息写入文件之前再进行设定.
        此处只是在内存中创建一个 Message 对象.*/

        return message;
    }


    public String getMessageId() {
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }


    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }

    public Integer getDeliverMode() {
        return basicProperties.getDeliverMode();
    }

    public void getDeliverMode(Integer mode) {
        basicProperties.setDeliverMode(mode);
    }


}
